import torch

x = torch.arange(12)

x.shape

x.numel() # 计算张量的元素总数456789

x.reshape(3, 4)

y = torch.zeros(4, 4)

z = torch.ones(4, 5)

x = torch.randn(3, 4) # 其中的 每个元素都从均值为0、标准差为1的标准高斯分布（正态分布）中随机采样

x = torch.tensor([[1, 2, 3, 3],[2, 2, 2, 2], [1, 2, 3, 4]]) # 直接指定赋值

x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y # **运算符是求幂运算

torch.exp(x) #计算e的x次幂

# 多个张量连结（concatenate），函数cat((...), dim = )
X = torch.arange(12, dtype=torch.float32).reshape(3, 4)  # 可以一步实现赋值和调整的操作，用.连接即可
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1) # dim=0表示连接行
# tensor([[ 0.,  1.,  2.,  3.],
        [ 4.,  5.,  6.,  7.],
        [ 8.,  9., 10., 11.],
        [ 2.,  1.,  4.,  3.],
        [ 1.,  2.,  3.,  4.],
        [ 4.,  3.,  2.,  1.]])，# 3+3=6.
#dim=1则是列tensor([[ 0.,  1.,  2.,  3.,  2.,  1.,  4.,  3.],
                  [ 4.,  5.,  6.,  7.,  1.,  2.,  3.,  4.],
                   [ 8.,  9., 10., 11.,  4.,  3.,  2.,  1.]])

# 还可以通过逻辑运算符构建tensor，同一位置元素一样即为true，否则为false
x_y = x==y

# 张量中的所有元素进行求和
x.sum()

# 广播机制----
# 某些情况下，即使形状不同， 我们仍然可以通过调用 广播机制（broadcasting mechanism）来执行按元素操作。这种机制的工作方式如下：
# 1. 通过适当复制元素来扩展一个或两个数组，以便在转换之后，两个张量具有相同的形状；2. 对生成的数组执行按元素操作
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a+b

# 索引访问张量的元素，用[-1]选择最后一个元素，可以用[1:3]选择第二个和第三个元素(左闭右开)
X[-1], X[1:3]
# 指定索引写入新元素
X[1, 2] = 9
# 指定某行某列写入元素写法（第一行和第二行进行所有列赋值，左闭右开）
X[0:2, :] = 12

# 节省内存，运行一些操作可能会导致为新结果分配内存；如：
before = id(Y)
Y = Y + X
id(Y) == before # 输出结果为：false
# 切片表示法将操作的结果分配给先前分配的数组，例如Y[:] = <expression>或者或X += Y来减少内存的开销
Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X+Y
print('id(Z):', id(Z)) #可以看到输出结果为：true，内存位置并没有改变

# 数据转换为其他Python对象，直接使用numpy()和tensor()
A = X.numpy()
B = torch.tensor(A)
type(A), type(B)
# 将大小为1的张量转换为Python标量，我们可以调用item函数或Python的内置函数
a = torch.tensor([3.5])
a, a.item(), float(a), int(a)

